package com.hh.aop;

import com.hh.annotation.Loggable;
import com.hh.entity.domain.SysLog;
import com.hh.entity.domain.User;
import com.hh.service.SysLogService;
import com.hh.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

/**
 * @author hanhui
 * @version 1.0
 * @description: 日志切面类
 * @date 2025/9/13 15:19
 **/
@Aspect
@Slf4j
//@Component
public class LoggingAspect {

    @Resource
    private SysLogService sysLogService;
    @Resource
    private UserService userService;

    @Around("@annotation(com.hh.annotation.Loggable)")
    public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Loggable loggable = method.getAnnotation(Loggable.class);

        String methodName = method.getDeclaringClass().getSimpleName() + "." + method.getName();
        String operation = loggable.operation().isEmpty() ? methodName : loggable.operation();
        SysLog sysLog = new SysLog();
        sysLog.setMethod(methodName);
        sysLog.setOperation(operation);

        // 获取请求信息（如果在Web环境中）
        HttpServletRequest request = null;
        try {
            request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        } catch (IllegalStateException e) {
            // 非Web环境，忽略
        }

        // 设置用户信息
        Long userId = null;
        String username = null;
        try {
            User loginUser = userService.getLoginUser(request);
            if (loginUser != null) {
                userId = loginUser.getId();
                username = loginUser.getUserName();
            }
        } catch (Exception e) {
            // 获取用户信息失败，使用默认值
            log.debug("无法获取当前登录用户信息");
        }

        sysLog.setUserId(userId);
        sysLog.setUsername(username);

        // 记录方法开始执行
        long startTime = System.currentTimeMillis();
        String params = loggable.recordParams() ? Arrays.toString(joinPoint.getArgs()) : "[已隐藏]";
        log.info("开始执行操作: {}, 参数: {}", operation, params);
        sysLog.setParams(params);
        sysLog.setCreateTime(new Date());

        if (request != null) {
            String remoteHost = request.getRemoteHost();
            sysLog.setIp(remoteHost);
            log.info("请求来自: {}", remoteHost.equals("0:0:0:0:0:0:0:1") ? "本地" : remoteHost);
        }

        Object result;
        try {
            // 执行目标方法
            result = joinPoint.proceed();

            // 记录方法执行完成
            long executionTime = System.currentTimeMillis() - startTime;
            log.info("操作完成: {}, 执行时间: {}ms, 结果: {}", operation, executionTime,
                    loggable.recordResult() ? result : "[已隐藏]");
        } catch (Throwable e) {
            // 记录方法执行异常
            long executionTime = System.currentTimeMillis() - startTime;
            log.error("操作异常: {}, 执行时间: {}ms, 异常信息: {}", operation, executionTime, e.getMessage(), e);
            sysLog.setOperation(operation + "(异常)");
            throw e;
        } finally {
            // 记录到数据库
            try {
                sysLogService.save(sysLog);
            } catch (Exception e) {
                log.error("保存操作日志到数据库失败: {}", e.getMessage(), e);
            }
        }
        return result;
    }
}